Skip to content

[WoA] Add manual cross-repository broker - #3025

Open
isVoid wants to merge 3 commits into
mainfrom
codex/woa-xrepo-public-manual-broker
Open

isVoid wants to merge 3 commits into
mainfrom
codex/woa-xrepo-public-manual-broker

Conversation

@isVoid

@isVoid isVoid commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Description

Tracks https://github.com/NVIDIA-dev/cuda-python-private/issues/584.

This is public PR A of the four-PR WoA cross-repository CI rollout. It adds two manually dispatched brokers and enables no automatic main trigger:

  • a transport-smoke broker that resolves an open same-repository PR head and dispatches the private smoke endpoint; and
  • an exact-run broker that validates one successful public main CI run, its producer jobs, SHA ancestry, artifact names, IDs, and server digests before dispatching private validation.

The private-dispatch App credential is referenced only by isolated jobs with permissions: {}. Those jobs do not check out source or download artifacts.

Depends on private foundation PR https://github.com/NVIDIA-dev/cuda-python-private/pull/650.

Rollout

After both foundation PRs merge:

  1. Run WoA cross-repository transport smoke against a public draft PR and verify cuda-python WoA integration / transport smoke completes neutral without a GB10 job.
  2. Run WoA exact public-main dispatch with known eligible run 37333876562 and verify the canonical check plus the minimal GB10 import test.
  3. Repeat with one deliberately invalid claim and verify failure occurs before GB10 allocation.

Validation

  • actionlint passes for both added workflows.
  • git diff --check passes.
  • Live read-only metadata validation found the exact expected Windows Arm64 artifact set on run 37333876562.
  • Execute both cross-repository smoke paths after merge.

Checklist

  • New or existing tests cover these changes where they can run before merge.
  • The design document is up to date with these changes.

@copy-pr-bot

copy-pr-bot Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@github-actions github-actions Bot added the CI/CD CI/CD infrastructure label Oct 5, 2026
@isVoid
isVoid marked this pull request as ready for review October 6, 2026 18:25
@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

📝 Summary

Summary by CodeRabbit

  • Chores
    • Added manually triggered workflows that check pull request and build-run details, including repository, branch, commit, and Windows Arm64 build artifacts.
    • Workflows stop when checks fail and verify the details of the resulting validation run.

Walkthrough

Adds two manually triggered workflows. One validates a pull request before dispatching a private smoke workflow. The other validates a public CI run and its Windows Arm64 artifacts before dispatching private validation. Both verify the returned private workflow run.

Changes

Cross-repository PR smoke

Layer / File(s) Summary
Resolve and validate pull request
.github/workflows/woa-transport-check.yml
The workflow accepts a PR number when the PR is open, targets main, comes from the expected repository, and has a valid head SHA. It exports the SHA and a correlation ID.
Dispatch and verify private smoke run
.github/workflows/woa-transport-check.yml
The workflow creates a scoped GitHub App token, dispatches the private workflow on ctk-next, and verifies the returned run’s repository, workflow, event, and branch.

Private WoA validation

Layer / File(s) Summary
Validate public run and artifacts
.github/workflows/woa-validation-dispatch.yml
The workflow checks the public CI run, commit position, producer job, and three expected unexpired artifacts. It exports resolved run and artifact data.
Dispatch and verify private validation
.github/workflows/woa-validation-dispatch.yml
The workflow creates a scoped GitHub App token, dispatches private validation on ctk-next with the resolved data, and verifies the returned run.

Priority: ⬇️ Low

Change: Feature

Merge Risk: 🟡 Moderate · up to 39414

Protect the private-dispatch credential and fix both run checks before merging; either manual broker can report failure after starting its private run.

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
.github/workflows/woa-private-dispatch.yml (1)

67-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

suggestion: Derive the CUDA build version from ci/versions.yml at public_sha. Do not hard-code 13.4.2.

Two values are fixed to 13.4.2:

  • the producer job name Build win-arm64, CUDA 13.4.2 / py3.13;
  • the artifact name cuda-bindings-python313-cuda13.4.2-win-arm64-<sha>.

In .github/workflows/ci.yml, both values come from .cuda.build.version (Lines 224-242 and 444-467). After the next CUDA version bump, this broker will reject every valid public run until someone edits this file. The failure is safe, but the broker becomes unusable.

Fix: read ci/versions.yml at public_sha with gh api repos/NVIDIA/cuda-python/contents/ci/versions.yml?ref=$public_sha. Then build the job name and the artifact names from .cuda.build.version.


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository: NVIDIA/cuda-python/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: 3bdf7831-9285-4563-bf65-3d0b14907b12
📥 Commits

Reviewing files that changed from the base of the PR and between 669e608 and eb4adea.

📒 Files selected for processing (2)
  • .github/workflows/woa-crossrepo-smoke.yml
  • .github/workflows/woa-private-dispatch.yml

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Comment thread .github/workflows/woa-validation-dispatch.yml
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

@isVoid isVoid self-assigned this Oct 7, 2026
@isVoid isVoid added the feature New feature or request label Oct 7, 2026
@isVoid isVoid added this to the cuda.core next milestone Oct 7, 2026
@lijinf2

lijinf2 commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

The PR needs manual trigger to run smoke test and dispatch-validate test, if I understand correctly. Are we able to test the manual trigger when the PR is open, or we need to merge the PR to allow manual trigger?

Comment thread .github/workflows/woa-validation-dispatch.yml
@lijinf2

lijinf2 commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

The PR introduces a two-phase design: a lightweight smoke check between the public and private repos to cheaply validate cross-repo connectivity/config, followed by a dispatch-validate step that verifies a merged main build and triggers real GB10 run. This lets connectivity/config issues surface cheaply in the first phase, before the costlier validation phase.

LGTM. I just have a few questions.

@isVoid

isVoid commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

Are we able to test the manual trigger when the PR is open, or we need to merge the PR to allow manual trigger?

There's a way, as pointed out here: https://github.com/NVIDIA-dev/cuda-python-private/pull/615#issuecomment-5797975839

But there's still a gap: push events require the inputs hard-coded in the workflow to trigger the test. And this PR would still require the private PR to be merged first before we can check the round trip.

@isVoid
isVoid requested a review from lijinf2 October 9, 2026 21:43

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository: NVIDIA/cuda-python/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: f257626e-4b8d-488c-bad5-26dc8c1e75d6
📥 Commits

Reviewing files that changed from the base of the PR and between eb4adea and 39414cc.

📒 Files selected for processing (2)
  • .github/workflows/woa-transport-check.yml
  • .github/workflows/woa-validation-dispatch.yml

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Comment thread .github/workflows/woa-transport-check.yml
Comment thread .github/workflows/woa-validation-dispatch.yml

@lijinf2 lijinf2 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

.path mismatched issue raised by coderabbit seems not blocking merge. We can confirm whether that is an actual issue after merge.

So we will have two new rows under Github Action. One is "woa-transport-check", and the other is "woa-validation-dispath". Does "woa-validation-dispath" changes status (i.e. green or red) before the private run finished or after?

@isVoid

isVoid commented Oct 12, 2026

Copy link
Copy Markdown
Contributor Author

Does "woa-validation-dispath" changes status (i.e. green or red) before the private run finished or after?

The check run will get updated depend on the stage of the private run. For example, after the dispatch is admitted, the private run will create a POST to update the check with "in progress" status. And once test finished, the report job will update the check with Completed status.

(.head.sha | test("^[0-9a-f]{40}$"))
' <<< "$pr" >/dev/null
public_sha=$(jq -r .head.sha <<< "$pr")
correlation_id="smoke:381173759:$PR_NUMBER:$public_sha:${GITHUB_RUN_ID}:${GITHUB_RUN_ATTEMPT}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: I assume the magic number here is the repo unique ID? In any case, why do we need that?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, fwiw I think agent is actioning in panic: repo name can change, but unique-id doesn't. But I agree using magic number here is over-engineering.

inputs: {
schema_version: "1",
public_repository: "NVIDIA/cuda-python",
public_repository_id: "381173759",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto, can we avoid hard-coding the magic number (given that the above line is also already hard-coding the repo name -- which can be also relaxed or replaced by e.g. ${{ github.event.repository.name }})?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, the workflow is already hardened by if: ${{ github.repository == 'NVIDIA/cuda-python' }}.

Comment on lines +9 to +14
workflow_dispatch:
inputs:
pr_number:
description: Open same-repository PR to receive the smoke Check Run
required: true
type: number

@leofang leofang Oct 12, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: I thought the security requirement is that we should not dispatch any un-merged PRs? How about taking no inputs and always dispatching from main for now?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This woa-transport-check is a smoke run, on the private side it doesn't trigger gb10 runners. It's only used to validate the github app works. The reported result will be posted on the PR's check run:

https://github.com/NVIDIA/cuda-python/pull/3025/checks

I think it's chosen this way to avoid polluting any existing commits that's already merged to main.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future PR this workflow is planned to be removed.

-H 'X-GitHub-Api-Version: 2026-03-10' \
"repos/NVIDIA-dev/cuda-python-private/actions/runs/$private_run_id")
jq -e '
.repository.id == 809898190 and

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto, maybe if we can just use the repo name instead of unique ID? (The name is already used above for building response anyway.)

Comment on lines +8 to +14
on:
workflow_dispatch:
inputs:
public_run_id:
description: Successful public main CI run containing the exact WoA artifacts
required: true
type: string

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: For convenience we can make this optional. We have a lookup-run-id script that can look up the latest run ID, see ci-nightly.yml:

workflow_dispatch:
inputs:
run-id:
description: >
Override the CI run ID to download artifacts from.
Leave empty to auto-detect the latest successful main run.
type: string
default: ''

Comment on lines +45 to +55
jq -e '
.repository.id == 381173759 and
.workflow_id == 155304118 and
.path == ".github/workflows/ci.yml" and
.event == "push" and
.head_branch == "main" and
.status == "completed" and
.conclusion == "success" and
(.head_sha | test("^[0-9a-f]{40}$"))
' <<< "$run" >/dev/null
public_sha=$(jq -r .head_sha <<< "$run")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto, this can be retrieved by passing --head-sha to lookup-run-id

artifacts-json: ${{ steps.resolve.outputs.artifacts_json }}
correlation-id: ${{ steps.resolve.outputs.correlation_id }}
public-producer-job-id: ${{ steps.resolve.outputs.public_producer_job_id }}
public-run-attempt: ${{ steps.resolve.outputs.public_run_attempt }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have enough sophisticated artifact passing across pipelines, but so far I don't see any need for run_attempt (because multiple attempts share the same run ID). Is it really needed?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(ditto for public_producer_job_id)

Comment on lines +78 to +110
expected_names=$(jq -n \
--arg sha "$public_sha" '[
"cuda-pathfinder-wheel",
("cuda-bindings-python313-cuda13.4.2-win-arm64-" + $sha),
("cuda-core-python313-win-arm64-" + $sha)
]')
artifacts_json='[]'
while IFS= read -r artifact_name; do
response=$(gh api --method GET \
-H 'X-GitHub-Api-Version: 2026-03-10' \
"repos/NVIDIA/cuda-python/actions/runs/$PUBLIC_RUN_ID/artifacts" \
-f name="$artifact_name" \
-F per_page=100)
artifact=$(jq -c -e \
--arg name "$artifact_name" '
if .total_count == 1 and
(.artifacts | length) == 1 and
.artifacts[0].name == $name and
.artifacts[0].expired == false
then .artifacts[0] | {id, name, digest}
else error("expected exactly one unexpired artifact named " + $name)
end
' <<< "$response")
artifacts_json=$(jq -c \
--argjson artifact "$artifact" \
'. + [$artifact] | sort_by(.name)' <<< "$artifacts_json")
done < <(jq -r '.[]' <<< "$expected_names")
jq -e '
length == 3 and
all(.[ ];
(.id | type == "number") and
(.digest | test("^sha256:[0-9a-f]{64}$")))
' <<< "$artifacts_json" >/dev/null

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: I am a bit confused by this code. Is artifacts_json a hard requirement? I think providing just the repo name and the run ID is enough to retrieve artifacts, akin to gh run download ...? All we need on the private repo side is a GH token that has actions:read.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI/CD CI/CD infrastructure feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants